<?php

App::import ('Model', 'Tweet');
App::import ('Model', 'User');
App::import ('Model', 'Account');
App::import ('Model', 'tattlrAccount');
App::import('Controller','Tweets');


class FutureTweet extends AppModel {

  var $uses = array('FutureTweet', 'Tweet');
  
  /**
   * Given a tweet id, this function either approves or disproves such a tweet, unless this tweet is non-existent.
   * @param  int $id tweetid
   * @return int     0 -> Tweet approved succesfully, 1 -> Tweet disproved successfully, 2 -> Tweet does not exist.
   * @author KareemYousry
   */
  public function approve($id) {

    $result = $this->find('all', array('conditions' => array('id' => $id), 'fields' => array('approved')));

    if($result) {

      if($result['0']['FutureTweet']['approved'] == '0'){ # The specified tweet has not yet been approved.
        $this->id = $id;
        $this->saveField('approved',true);
        return 0;

      } else { # Disprove Tweet
        $this->id = $id;
        $this->saveField('approved',false);
        return 1;
      }

    } else { # The specified Tweet does not exist.
      return 2;
    }
  }

    /**
    *  The function returns the number of repetitions of a certain tweet with text = $text in an event with id = eventID
    * @param  int $eventID.
    * @param  String $text
    * author : "Mina Samy"
    */
  public function getrepetitions($eventID , $text) 
   {
    return $this->find('count' , array('conditions'=>array("FutureTweet.eventID" => $eventID , "FutureTweet.tweetText" => $text)));
   }
  



    /**
    * Deletes all the tweets of a certain event with ID = $id from the database 
    * @param  int $id.
    * author : "Mina Samy"
    */
    public function deleteeventtweets($id = null)
  {
      $this->deleteAll(
                    array('eventID <=' => $id));
  }


  /**
    * Deletes all the repetitions of a certain tweet in the event
    * @param  String $text.
    * @param  int $eventID
    * @param  Datetime $subtime
    * author : "Mina Samy"
    */
    public function deleterepeated($text = null , $eventID = null , $subtime)
  {
      $this->deleteAll(
                    array('eventID' => $eventID , 'sub_time' => $subtime , 'tweetText' => $text ));
  }




 
/*
      * Description of Function ApproveEvent
	  * @eventID
      * The function sets the approval of all the tweets with eventID = $eventID to be = $approveornot
      * @author Mina Samy
      */
	public function ApproveEvent($eventID = null , $approveornot = null)
	{
		 $this->updateAll(
                    array('approved' => $approveornot),
                    array('eventID <=' => $eventID));
					
	}

	/*
      * Description of Function EventSaving
	  * @eventID
	  * @saveornot
      * The function saves the Event of tweets by setting the saved attribute of all the tweets that belong to this event with eventID = $eventID to $saveornot
	  * such that if $saveornot is 1 then the event is saved and not submitted yet if 0 then its not also if an event is saved which means it is being editted
	  * it has to be reapproved.
      * @author Mina Samy
      */
	public function EventSaving($eventID = null , $saveornot = null , $permission = null)
	{
		 $this->updateAll(
                    array('saved' => $saveornot),
                    array('eventID' => $eventID));
					
					
			if($saveornot == 1 AND $permission == 1)
			{
				 $this->updateAll(
                    array('approved' => 0),
                    array('eventID' => $eventID));
			}
	}

	/*
      * Description of Function getEventFutureTweets
	  * @eventID
      * The function getEventFutureTweets returns all the tweets which are not posted yet to twitter and belong to to the event with $eventID
      * @return tweets of the event $eventID
      * @author Mina Samy
      */
	public function getEventFutureTweets($eventID = null)
	{
		 $conditions = array("FutureTweet.eventID" => $eventID);
     return $this->find('all',array('conditions' => $conditions));
	}
	
  


		/*
      * Description of Function getEventFutureTweets
	  * @eventID
      * The function getEventFutureTweets returns all the tweets which are not posted yet to twitter and belong to to the event with $eventID
      * @return tweets of the event $eventID
      * @author Mina Samy
      */
	public function isApproved($eventID = null)
	{
	 $conditions = array("FutureTweet.eventID" => $eventID , "FutureTweet.approved" => 1);
     $countapproved = $this->find('count',array('conditions' => $conditions));
	 	
		$conditions1 = array("FutureTweet.eventID" => $eventID);
     $countall = $this->find('count',array('conditions' => $conditions1));
	 if($countall == $countapproved)
	 {
		return true;
	 }
	 else 
	 {
		return false;
	 }
	}
	
	
		/*
      * Description of Function getEventFutureRepeatedTweet 
	  * @eventID
      * The function getEventFutureTweets returns all the tweets which are not posted yet to twitter and belong to to the event with $eventID and have 
	  * tweetText $text 
      * @return tweets of the event $eventID tweetText $text 
      * @author Mina Samy
      */
	public function getEventFutureRepeatedTweet($eventID = null , $text = null)
	{
		 $conditions = array("FutureTweet.eventID" => $eventID , "FutureTweet.tweetText" => $text);
     return $this->find('all',array('conditions' => $conditions));
	}
	
	
	/**
   * This function determines whether the newly inserted tweet violates the specifed the minimum duration
   * specified for the twitter account by comparing its release_time with both the tweet that is to be
   * posted before and after the specifed tweet. If no conflict occurs, the tweet is added to the futre_tweets
   * table.
   * @param array $tweet The new tweet to be added
   * @return 0 -> Successful, -1 -> sameText exists, -2 -> minimum duration violated, -3 -> unknown error, -4 -> non-existent account
   * -5 -> The supplied input is null. 
   * @author  Kareem Yousry
   */
  public function insertTweet($tweet) {
    $post = new post();
    $account = new Account();
    $tattlrAccount = new tattlrAccount();

    if(isset($tweet['reply_to'])) {
      $this -> create();
      if ($this -> save(array('FutureTweet' => $tweet))) { # If the tweet was added successfully.
        return 0; 

      } else { # An unknown error has occured.
        return -3; 
      }
    }

    if(is_null($tweet)){
      return -5;
    }

    if($account -> checkAccount($tweet['accID'])) {
      # Tweet to-be added to the buffer.
      $current = $tweet['release_date']; 
      # Last tweet posted on twitter.
      $last = $post -> getLastTweet($tweet['accID']); 
      # Tweet to-be posted before the new tweet.
      $before = $this -> getTweetBefore($tweet['accID'], $tweet['release_date']); 
      # Tweet to-be posted after the new tweet.
      $after = $this -> getTweetAfter($tweet['accID'], $tweet['release_date']); 
      # Get the minimum duration of the given account.
      $minDuration = $tattlrAccount -> getMinDuration($tweet['accID']);

      $intervals = array();

      if ($before != -1) {
        $intervals['before'] = $before;
      }

      if ($after != -1) {
        $intervals['after'] = $after;
      }

      if ($last != -1) {
        $intervals['last'] = $last;
      }

      foreach ($intervals as $interval) {
        $interval = abs(strtotime($current) - strtotime($interval));
        $interval = $interval / 60;

        if($interval < $minDuration) { # If the minimum duration does not hold.
          return -2;
        }
      }

      $this -> create();
      if ($this -> save(array('FutureTweet' => $tweet))) { # If the tweet was added successfully.
        return 0; 

      } else { # An unknown error has occured.
        return -3;
      }
      
    } else {
      return -4;
    }
  }
	
  /**
   * Given an account ID and a release time for a new tweet, this function returns
   * the tweet to be posted right before the supplied release time.
   * @param  int $accID account ID of the tweeting account.
   * @param  String $time  The release time of the new tweet
   * @return Mixed returns a string represented the release_time of the tweet before
   * or -1 if no such tweets exist.
   * @author Kareem Yousry.
   */
  private function getTweetBefore($accID, $time) { # Works Great.
        
    $res = $this->find('first', array('conditions' => array("FutureTweet.accID" => $accID, 'FutureTweet.release_date <=' => $time), 
        'fields' => array('FutureTweet.release_date'), 
        'order' => array('FutureTweet.release_date DESC')));

    if($res != NULL) {
        return $res['FutureTweet']['release_date'];
    } else {
        return -1; //No such tweets
    }
  }

  /**
   * Given an account ID and a release time for a new tweet, this function returns
   * the tweet to be posted right after the supplied release time.
   * @param  int $accID account ID of the tweeting account.
   * @param  String $time  The release time of the new tweet
   * @return Mixed returns a string represented the release_time of the upcoming 
   * tweet or -1 if no such tweets exist.
   * @author Kareem Yousry.
   */

  private function getTweetAfter($accID = NULL, $time = NULL) { # Works Great.
      
    $res = $this->find('first', array('conditions' => array("FutureTweet.accID" => $accID, 'FutureTweet.release_date >' => $time), 
        'fields' => array('FutureTweet.release_date'), 
        'order' => array('FutureTweet.release_date ASC')));

    if($res != NULL){
        return $res['FutureTweet']['release_date'];
    } else {
        return -1; //No such tweets
    }
  }

  /**
   * Given an account ID, a release time for a new tweet, and the text of a new tweet, this function checks
   * if there exists a tweet in the database with the same tweet text where the difference between the supplied 
   * timing and the release date of such a tweet already present in the database exceeds one day
   * @param  int $accID account ID of the tweeting account.
   * @param  String $time The release time of the new tweet
   * @param  String $tweetText Text of the tweet to be checked against.
   * @return int returns 0 if there is no violation, returns -1 a tweet with the same text already exists.
   * @author Kareem Yousry. 
   */

  private function getTweetSameText($accID = NULL, $time = NULL, $tweetText = NULL) { # Works Great.

    $before = $this->find('first', array('conditions' => array("FutureTweet.accID " => $accID,
      'FutureTweet.release_date <=' => $time,'FutureTweet.tweetText' => $tweetText), 
        'fields' => array('FutureTweet.release_date'), 
        'order' => array('FutureTweet.release_date ASC')));

    $after = $this->find('first', array('conditions' => array("FutureTweet.accID " => $accID,
      'FutureTweet.release_date >' => $time, 'FutureTweet.tweetText' => $tweetText), 
        'fields' => array('FutureTweet.release_date'), 
        'order' => array('FutureTweet.release_date ASC')));

    # Checks if there are no tweets before or after, in which case it is safe to proceed.
    if(($before == false) && ($after == false)) {
      return 0;
    }

    $intervals = array();

    if($before != false) {
      $before = $before['FutureTweet']['release_date'];
      $intervals['before'] = $before;
    }

    if($after != false) {
      $after = $after['FutureTweet']['release_date'];
      $intervals['after'] = $after;
    }

    foreach($intervals as $interval) {
      $interval = abs(strtotime($time) - strtotime($interval));
      # Change seconds into days.
      $interval =  $interval / (60 * 60);

      # Min time by twitter (1 day) was not satisfied.
      if($interval < 24) {
        return -1; 
      }
    }
    # Safe to proceed.
    return 0; 
  }
    
  /**
   * Description of postingTweet
   *
   *
   *find all tweets that have to be posted at the moment that is done by filtering the data base compering the release_date of the tweet
   *by the current time. Once the table Future_tweets is filtered with all the tweet that must be posted at the current time, the tweets will be stored
   *in an array. 
   *Before it starts posting on twitter it checks wether the tweet is already posted before or not, if it was posted it deletes it from twitter and then post it again to avoid twitter policy in repeated tweets in the same day
   *Then we call the postTweet function to post the Tweet on Twitter then we delete the tweet form the table FutureTweet.
   *To delete the tweet from the table we have to pass the id of the tweet since delete function can only take id as parameter. Therefore we need to loop on the array
   *where all tweets that should be posted now in it , and call post_to_twitter function and if the function returned true that the tweet is posted then delete it from the table
   *else keep looping until it is posted 
   *
   *@return void
   * @author Youssef Madkour
   */
    
    public function postingTweet() {

        $tweetsController  = new TweetsController();
        $repeatedTweet = new Post();

        $current_time = date('Y-m-d H:i:s');
        $tem = $this->getFutureTweet($current_time);
        $condition = array("FutureTweet.release_date <=" => $current_time ,"FutureTweet.approved" => '1',"FutureTweet.saved" =>'0' );    
        $length = count($tem);
        if($length != 0){
      for($i= $length; $i>=0 ; $i--){

          $t = $this->field('id', array("FutureTweet.release_date <=" => $current_time ,"FutureTweet.approved" => '1' ,"FutureTweet.saved" =>'0'), '');
          $tweet = $this->find('first',array('conditions' => $condition));
        
          $condition2 = array("Post.accID" => $tweet['FutureTweet']['accID'],"Post.text"=> $tweet['FutureTweet']['tweetText']);
          $r= $repeatedTweet->find('all',array('conditions' => $condition2));
        
          if(count($repeatedTweet->find('all',array('conditions' => $condition2,'fields' => array('Post.postID')))) > 0){
            $c = count($repeatedTweet->find('all',array('conditions' => $condition2,'fields' => array('Post.postID'))));
           
             $tweetsController ->deletetweetCron($r[($c-1)]['Post']['postID'],$r[($c-1)]['Post']['accID']);

            
          }

          if($tweet['FutureTweet']['imageName'] == NULL){

           if( ClassRegistry:: init('tweet')->post_to_twitter($tweet['FutureTweet'])){
           $this->delete( $t );
           }}
           else{
            if($tweetsController->post_image_tweet($tweet['FutureTweet'])){
               $this->delete( $t );

            }

           }


      $i = count($this->find('all',array('conditions' => $condition,'fields' => array('FutureTweet.id'))));
      }
    }

     }

    /*
      * Description of getFutureTweet
      * @time 
      *@return the id of the tweet which should be posted  
      *get all the tweets for all the accounts that should be posted at the current time  
      *
      * @author Youssef Madkour
      */
    
    public function getFutureTweet($time = NULL ){
        
       	  $current_time = date('Y-m-d H:i:s');
	  	  $condition = array("FutureTweet.release_date <=" => $current_time ,"FutureTweet.approved" => '1',"FutureTweet.saved" =>'0' );
		  $tem=$this->find('all',array('conditions' => $condition,'fields' => array('FutureTweet.id')));
	  
	       return $tem;
    }
	/*
      * Description of update
      * $current_time,$userID,$String_TweetText,$accountID
      *updates the fields of the array to $current_time,$userID,$String_TweetText,$accountID
      *
      * @author sherif ismail
      */
	 		public function update($current_time,$userID,$String_TweetText,$accountID){
			$data['FutureTweet']['tweetText'] = $String_TweetText;
			$data['FutureTweet']['userID'] = $userID;
			$data['FutureTweet']['sub_time'] = $current_time;
			$data['FutureTweet']['release_date'] = $current_time;
			$data['FutureTweet']['accID'] = $accountID;
			$data['FutureTweet']['saved'] = false;
			return $data;
	}
	  /*
      * Description of updateapproved
      * $data 
      *updates the field of approved in the array to 1
      *
      * @author sherif ismail
      */
	public function updateapproved($data){
	$data['FutureTweet']['approved'] = 1;
	return $data;
	}
	public function updateapprovedfalse($data){
	$data['FutureTweet']['approved'] = false;
	return $data;
	}
		 /*
      * Description of setreplyto
      * $data ,$replyid
      *updates the field of replyto in the array to $replyid
      *
      * @author sherif ismail
      */
	public function setreplyto($data,$replyID){
    $data['FutureTweet']['reply_to']= $replyID;
	return $data;
	}
	
	        /*
      * Description of isApprove
      * @param : id
      * @return the tweets with approved equals to 1 
      * get tweets with approved equals to 1 
      * @author Amr Magdy
      */
        
      public function isApprove($id = null)
	{   
          $approve = $this->find('all', array('conditions' => array('id' => $id), 'fields' => array('approved')));
          return $approve[0]['FutureTweet']['approved'] ;
	}
        
        /*
      * Description of Function ApproveTweet
	  * @param : id , approveornot
	  * @return: void
      * The function sets the approval of all the tweets with id = $id to be = $approveornot
      * @author Amr magdy
      */
	public function ApproveTweet($id = null , $approveornot = 1)
	{
		 $this->updateAll(
                    array('approved' => $approveornot),
                    array('id ' => $id));
					
	}
        
          /*
      * Description of isrejected
      * @param : id
      *@return the tweets with approved equals to 0
      *get tweets that are not yet approved
      * @author Amr Magdy
      */
        public function isrejected($id = null)
	{
          $approve = $this->find('all', array('conditions' => array('id' => $id), 'fields' => array('approved')));
          return $approve[0]['FutureTweet']['approved'] ;
	}
        
        /*
      * Description of Function RejectTweet
	  * @param : id ,approveornot
	  * @return: void
      * The function sets the approval of all the tweets with id = $id to be = $approveornot
      * @author Amr magdy
      */
	public function RejectTweet($id = null , $approveornot = 0)
	{
		 $this->updateAll(
                    array('approved' => $approveornot),
                    array('id' => $id));
					
	}
        
        /*
      * Description of approvedTweets
      *@return the tweets with approved equals to 1 
      *get all approved tweets 
      * @author Amr Magdy
      */
        
        public function approvedTweets(){
         
           
            return $this->query("select *
		from users User join future_tweets FutureTweet on User.userID=FutureTweet.userID
		where FutureTweet.approved = 1");
           
        }
        
        /*
      * Description of rejectedTweets
      *@return the tweets with approved equals to 0 
      *get tweets that are not approved yet 
      * @author Amr Magdy
      */
        public function rejectedTweets(){
            
            return $this->query("select *
		from users User join future_tweets FutureTweet on User.userID=FutureTweet.userID
		where FutureTweet.approved = 2");
            
        }
		  /*
      * Description of pendingTweets
      *@return the tweets with approved equals to 0 
      *get tweets that are not approved yet nor rejected
      *
      * @author Amr Magdy
      */
        public function pendingTweets(){
            
            return $this->query("select *
		from users User join future_tweets FutureTweet on User.userID=FutureTweet.userID
		where FutureTweet.approved = 0");
            
        }
        
        /*
      * Description of countPendingTweets
      *@return the tweets with approved equals to 0 
      *get tweets that are not approved yet nor rejected
      *
      * @author Amr Magdy*/
      
        public function countPendingTweets(){
            
            $num =  $this->query("select count(*)
		from users User join future_tweets FutureTweet on User.userID=FutureTweet.userID
		where FutureTweet.approved = 0");
            //debug($num[0][0]['count(*)']);
            return $num[0][0]['count(*)'];
            
        }
        
        /*
      * Description of MyTweets
      * @param :userID 
      * @return the tweets of the given user
      * get tweets that are made by the given user id 
      *
      * @author Amr Magdy
      */
        public function MyTweets($userID){
            
            return $this->query("select *
		from users User join future_tweets FutureTweet on User.userID=FutureTweet.userID
		where FutureTweet.userID = ".$userID."");
        }
        
        /*
      * Description of getUser
      * @param : userID 
      * @return all fields in the future tweets table for the account the user works for
      *
      * @author Amr Magdy
      */
        public function getUser($accID){
            
            return $this->query("select * from users User join future_tweets FutureTweet on User.userID=FutureTweet.userID where FutureTweet.accID=".$accID."");
        }
		
		/*
      * Description of getUser1
      * @param : userID , accID
      * @return all fields in the future tweets table for the account the user works for
      * @author Amr Magdy
      */
        public function getUser1($accID , $userID){
            
            return $this->query("select * from users User join future_tweets FutureTweet on User.userID=FutureTweet.userID where FutureTweet.accID='".$accID."' and User.userID =' ".$userID."'");
        }
		
		/* Description of addRandomVariance function
      * 
      * @TweetIDs
      * 
      * The function addRandomVariance functions as follows, it loops over the length of the given
      * array (tweetIDs), and in each loop it extracts the supposed release_date spliting out all its 
      * content, and adding the random variance to the number of minutes in the release date handling 
      * the case if the number of minutes exceeded 60.
      * 
      * @return void
      * 
      * @author: Ahmad AboulAzm
      * 
      */

    public function addRandomVariance($TweetIDs) {
        $n = sizeof($TweetIDs);
        $randomAddition = Math.rand(1, 60);
        for ($i = 0; $i < $n; $i++) 
        {
		
            $currentID = $TweetIDs[$i];
            $array = $this->find('all', array('fields' => array('release_date'),
                'conditions' => array('id' => $currentID)));
          
            $dates = $array[0]['FutureTweet']['release_date'];
            
            
            list($year, $month, $day, $Clock) = split('[ .-]', $dates);
            
            list($hour, $minute, $second) = split('[:.-]', $Clock);
            
            $minute =(($minute + $randomAddition) % 60);
            
            
            
            $placedTime = $year.'-'.$month.'-'.$day.' '.$hour.':'.$minute.':'.$second;
            $data = array('id' => $currentID, 'release_date' => $placedTime);
            
            $this->save($data);
            //$randomAddition = $randomAddition * 2;
        }
    }
    
    
    /* Description of TweetsApproval function
     * @ TweetID
     * @ $reply
     *  
     * The function TweetsApproval updates the approval of a certain tweet in the futureTweets table, by
     * taking the tweet id and the reply weather it it rejected '0' or accepted '1' , and if the user
     * entered something different than 0 and 1 , a printed message appears to him
     *
     * @return void
     *  
     * @author: Ahmad AboulAzm
     */ 
    
    public function TweetsApproval($TweetID, $reply)
    {
        if (($reply != '0') && ($reply != '1'))
        {
            print_r('The reply should be in the from of bit, 1 for acceptance and 0 for rejection');
        }
        
        else 
        {
        
            $this->FutureTweet->updateAll(
                    array('approved' => $reply),
                    array('id <=' => $TweetID));
        }
    }
	
    public function findtweetstest()
  {
     return $this->FutureTweet->find('all', array('conditions' => array('eventID' => 600)));
  }
   /* Description of deleteJETweet
     * This function takes as parameter the ID of a tweet and deletes it from the database
     * returns true if found and deleted, false if not found
     *
     *
     * @access public
     * @param int tweetID
     * @return boolean
     *  
     *
     *  
     * @author: "Mark Milad"
     */ 
   public function deleteJETweet($tweetID){
       return $this->delete($tweetID);
   }

    /**
     * Checks whether or not a tweet exists, given a tweet id.
     * @param  int $id tweetid
     * @return boolean     [description]
     */
    public function tweetExists($id) {
      $result = $this->find('all', array('conditions' => array('id' => $id)));

      if($result){
        return true;

      } else {
        return false;
      }
   }
}